;;;This are the testcases of the Port Shen to Clojure project.
;;;All this testcases are passed at the moment.
;;;
;;;Here test/is the list of the testcases, which has the same order like in this file.
;;;This list can be used to find the special testcase.
;;;
;;; --------- = ----------
;;; --------- defun & lambda & let ----------	
;;; --------- errors (Exception handling)----------
;;; --------- + ----------
;;; --------- - ----------
;;; --------- * ----------
;;; --------- / ----------
;;; --------- < ----------
;;; --------- <= ----------
;;; --------- > ----------
;;; --------- >= ----------
;;; --------- if ----------
;;; --------- number? ----------
;;; --------- boolean? ----------
;;; --------- and ----------
;;; --------- or ----------
;;; --------- set & value ----------
;;; --------- string & string? & tlstr & cn & pos----------
;;; --------- cons & cons? & hd & tl----------
;;; --------- absvector & absvector? & <-address & address-> ----------
;;; --------- eval-without-macros ' & freeze & thaw ----------
;;; --------- intern & function ----------
;;; --------- get-time ----------
;;; --------- stream (write and read in files) ----------
;;; --------- n->string -------------
;;; --------- special tests ---------


(ns shen.testcases
  (:refer-clojure :exclude [string? cond let + number? * - / intern or set < <= cons str = > >= and pr type])
  (:use shen.primitives)
  (:require [clojure.test :as test]))

;;; --------- = ----------
(test/is (eval-without-macros '(= 2 2)))
(test/is (eval-without-macros '(= true true)))
(test/is (eval-without-macros '(= "foo" "foo")))
(test/is (eval-without-macros '(= 'bar 'bar)))

(test/is (= (eval-without-macros '(= 2 3)) false))
(test/is (= (eval-without-macros '(= "foo" "bar")) false))
(test/is (= (eval-without-macros '(= foo bar)) false))
(test/is (= (eval-without-macros '(= true false)) false))

;;; --------- defun & lambda & let ----------
(defun f(x) (lambda y (+ x y)))
(test/is (= (eval-without-macros '((f 3) 2)) 5))
(test/is (= 10 (eval-without-macros '(let x 5 (* 2 x)))))

;;; --------- errors ----------
(test/is (= 1 (eval-without-macros '(/ 1 1))))
(test/is (= (eval-without-macros '(trap-error (/ 1 0) (lambda E (error-to-string E)))) "division by zero"))
(test/is (= (eval-without-macros '(trap-error (/ 1 0) (lambda E -1))) -1))
(test/is (= (eval-without-macros '(trap-error (/ 1 1) (lambda E -1))) 1))
(eval-without-macros '(trap-error (set newError (simple-error "testError")) (lambda E (error-to-string E))))


;;; --------- + ----------
(test/is (= (eval-without-macros '(+  2 3)) 5))
(test/is (= (eval-without-macros '(+  2 -3)) -1))

;;; --------- - ----------
(test/is (= (eval-without-macros '(-  2 3)) -1))
(test/is (= (eval-without-macros '(-  2 -3)) 5))


;;; --------- * ----------
(test/is (= (eval-without-macros '(*  2 3)) 6))
(test/is (= (eval-without-macros '(*  2 -3)) -6))


;;; --------- / ----------
(test/is (= (eval-without-macros '(/  5 2)) 2.5))
(test/is (= (eval-without-macros '(/  4 -4)) -1))


;;; --------- < ----------
(test/is (= (eval-without-macros '(<  1 2)) true))
(test/is (= (eval-without-macros '(<  4 4)) false))
(test/is (= (eval-without-macros '(<  4 0)) false))

;;; --------- <= ----------
(test/is (= (eval-without-macros '(<=  1 2)) true))
(test/is (= (eval-without-macros '(<=  4 4)) true))
(test/is (= (eval-without-macros '(<=  4 0)) false))


;;; --------- > ----------
(test/is (= (eval-without-macros '(>  3 2)) true))
(test/is (= (eval-without-macros '(>  4 4)) false))
(test/is (= (eval-without-macros '(>  2 4)) false))


;;; --------- >= ----------
(test/is (= (eval-without-macros '(>=  3 2)) true))
(test/is (= (eval-without-macros '(>= 4 4)) true))
(test/is (= (eval-without-macros '(>  2 4)) false))


;;; --------- if ----------
(test/is (eval-without-macros '(if true true false)))
(test/is (eval-without-macros '(if false false true)))


;;; --------- number? ----------
(test/is (= (eval-without-macros '(number?  3)) true))
(test/is (= (eval-without-macros '(number?  -3.4)) true))
(test/is (= (eval-without-macros '(number?  "fuu")) false))
(test/is (= (eval-without-macros '(number?  'bar)) false))


;;; --------- and ----------
(test/is (and true true true))
(test/is (= (and true false true) false))
(test/is (= (and true false true) false))
;(test/is (= -1 (trap-error (and 2 true) (lambda E -1))))


;;; --------- or ----------
(test/is (or true true true))
(test/is (or true false true))
(test/is (or (and false false false) true))
;(test/is (= -1 (trap-error (or 2 true) (lambda E -1))))


;;; --------- set & value ----------
(eval-without-macros '(set x 5))
(test/is (= (eval-without-macros '(value x)) 5))
(eval-without-macros '(set x "foo"))
(test/is (= (eval-without-macros '(value x)) "foo"))
;(test/is (= -1 (eval-without-macros '(trap-error (value valueTest) (lambda E -1)))))


;;; --------- string & string? & tlstr & cn & pos----------
(test/is (string? "bar"))
(test/is (string? (str "foo")))
(test/is (string? (str 2)))
(test/is (string? (str true)))
(test/is (string? (str 'bar)))
(test/is (= "bar" (str 'bar)))
(test/is (= (string? 55) false))
(test/is (= (tlstr "foobar") "oobar"))
(test/is (= (cn "foo" "bar") "foobar"))
(test/is (= (pos "bar" 2) "r"))


;;; --------- cons & cons? & hd & tl----------
(test/is (cons? [2 1 1 "foo"]))
(test/is (cons? (cons 3 [2 1 1 "foo"])))
(test/is (= (cons? 55) false))
(test/is (= (hd [2 1 1]) 2))
(test/is (= false (= (hd [2 1 1]) 1)))
(test/is (= (hd (tl [2 1 1])) 1))



;;; --------- absvector & absvector? & <-address & address-> ----------
(eval-without-macros '(set v (absvector 5)))
(test/is (eval-without-macros '(absvector? (value v))))
(test/is (= (eval-without-macros '(absvector? v)) false))
(test/is (= (absvector? 2) false))
(test/is (= (absvector? "foo") false))
(eval-without-macros '(address-> (value v) 2 5))
(test/is (= (eval-without-macros '(<-address (value v) 2)) 5))



;;; --------- eval-without-macros ' & freeze & thaw ----------
(test/is (= (eval-without-macros '(+ 4 5)) 9))
(test/is (= 4 (+ 2 2)))
(test/is (= (= 4 (freeze (+ 2 2))) false))
;(test/is (= 4 (thaw (freeze (+ 2 2)))))	;thaw test/is no part of KLambda


;;; --------- intern & function ----------
(eval-without-macros '(set x 5))
(test/is (= (eval-without-macros '(value x)) 5))
(test/is (= (eval-without-macros '(value (intern "x"))) 5))
(eval-without-macros '(defun x (y) (+ y y)))
(eval-without-macros '(set t (function x)))
(test/is (= (eval-without-macros '((value t) 10)) 20))
(test/is (= (= (eval-without-macros '((value t) 10)) 21) false))


;;; --------- get-time ----------
(test/is (> (eval-without-macros '(get-time real)) 100000))

;;; --------- stream ----------
(eval-without-macros '(set fileName (cn (str (get-time real)) ".txt")))
(eval-without-macros '(set writeFile (open file (value fileName) out)))
(eval-without-macros '(pr "foobar" (value writeFile)))
(eval-without-macros '(close (value writeFile)))
(eval-without-macros '(set readFile (open file (value fileName) in)))
(test/is (= 102 (eval-without-macros '(read-byte (value readFile)))))
(test/is (= 111 (eval-without-macros '(read-byte (value readFile)))))
(test/is (= (= 102 (eval-without-macros '(read-byte (value readFile)))) false))
(eval-without-macros '(close (value readFile)))
(try (clojure.java.io/delete-file (eval-without-macros '(value fileName))) (catch Exception e nil))

;;; --------- n->string -------------
(test/is (= "d" (n->string 100)))
(test/is (= "h" (n->string 104)))
(test/is (= "(" (n->string 40)))
(test/is (= false (= "d" (n->string 101))))
;(test/is (= -1 (eval-without-macros '(trap-error (n->string -10) (lambda E -1)))))
;(test/is (= -1 (eval-without-macros '(trap-error (n->string 4000) (lambda E -1)))))


;;; --------- special tests ---------
;(test/is (= [] ()))
;(test/is (= -1 (eval-without-macros '(trap-error ((4 3 2)) (lambda E -1)))))
;(test/is (= -1 (eval-without-macros '(trap-error ([4 3 2]) (lambda E -1)))))
;(test/is (= -1 (eval-without-macros '(trap-error (+4 2) (lambda E -1)))))
;(test/is (= -1 (eval-without-macros '(trap-error (+ 4 "2") (lambda E -1)))))
;(test/is (= -1 (eval-without-macros '(trap-error (+ 4 specialTest) (lambda E -1)))))
;(test/is (= -1 (eval-without-macros '(trap-error (+ 4 true) (lambda E -1)))))
;(test/is (= -1 (eval-without-macros '(trap-error (+ 4 specialTest) (lambda E -1)))))

(println "done")
